/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.tabbedproperties.composites;

import org.eclipse.gef.commands.CommandStack;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory;

import com.cea.papyrus.core.editor.CommandStackUtils;
import com.cea.papyrus.core.ui.dialogs.SynchronizeWithGenericElementsDialog;
import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagram.classdiagram.commands.SynchronizationWithBoundElementsCommand;
import com.cea.papyrus.umlutils.TemplateableElement;

/**
 * Base class for a complex section composite. This composite has a label, a
 * table that describes a tree structure, and four buttons on the side of the
 * table to add an element into the table, remove selected element(s), move up
 * or down the selected element.
 * 
 * @author Remi SCHNEKENBURGER
 */
public class SynchronizeWithGenericElementsComposite implements ISectionComposite {
	
	/**
	 * main composite of this complex composite.
	 */
	protected Composite composite;
	
	/**
	 * Label above the table.
	 */
	protected CLabel label;
		
	/**
	 * Button that adds an element.
	 */ 
	protected Button synchronizeButton;
		
	// listeners for buttons
	/**
	 * Listener for the add button.
	 */
	protected MouseListener synchronizeButtonlistener;
	
	/**
	 * Element selected in the Papyrus modeler.
	 */
	protected TemplateableElement element;
		
	/**
	 * returns the element that is selected in Papyrus tool, for which
	 * properties are displayed in the property section.
	 * 
	 * @return the element
	 */
	public TemplateableElement getElement() {
		return element;
	}

	/**
	 * Sets the element that holds property displayed in property section.
	 * 
	 * @param element the element to set
	 */
	public void setElement(TemplateableElement element) {
		this.element = element;
		if (element != null) {
			synchronizeButton.setEnabled(!this.element.isSynchronizedWithTemplates()) ;
		}
	}
	
	/**
	 * Constructor.
	 * 
	 * @param name text of the Label on the top left of this composite
	 */
	public SynchronizeWithGenericElementsComposite() {
		this.synchronizeButtonlistener = new SynchronizeButtonlistener();
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.ui.composites.ISectionComposite#createContent(org.eclipse.swt.widgets.Composite, org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory)
	 */
	/**
	 * 
	 * 
	 * @param factory 
	 * @param parent 
	 * 
	 * @return 
	 */
	public Composite createContent(Composite parent,
			TabbedPropertySheetWidgetFactory factory) {
		composite = factory.createFlatFormComposite(parent);

		FormData data;

		/////////////////////////////////////////////////////////////////////////////
		// Create and place button vertically on the left side
		// Button : Add Element
		// Button Delete Element
		synchronizeButton = factory.createButton(composite, "",  SWT.PUSH);
		synchronizeButton.setVisible(true);
		synchronizeButton.setText("Synchronize with bound templates") ;
		synchronizeButton.setToolTipText("Update the features owned by this element according to the defined template bindings \n (NOTE: Only synchronization of properties is supported for the moment.)");
		data = new FormData();
		// data.top   = new FormAttachment(addButton, ITabbedPropertyConstants.HSPACE);
		data.top  = new FormAttachment(0, 0);
		data.right = new FormAttachment(100, -ITabbedPropertyConstants.HSPACE);
		synchronizeButton.addMouseListener(synchronizeButtonlistener) ;
//		boolean toto = element.isSynchronizedWithTemplates() ;
//		synchronizeButton.setEnabled(!element.isSynchronizedWithTemplates()) ;
		return composite;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.ui.composites.ISectionComposite#refresh()
	 */
	/**
	 * 
	 */
	public void refresh() {
	}
	
	/**
	 * Sets the layout data to the main composite of this complex element.
	 * 
	 * @param data the new LayoutData
	 */
	public void setLayoutData(Object data) {
		composite.setLayoutData(data);
	}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	public Composite getMainComposite() {
		return composite;
	}
	
	/**
	 * Returns the CommmandStack of the current editor.
	 * 
	 * @return the CommmandStack of the current editor
	 */
	public CommandStack getCommandStack() {
		return (CommandStack)getActiveEditor().getAdapter(CommandStack.class);
	}
	
	/**
	 * Returns the current Editor.
	 * 
	 * @return the current editor
	 */
	public IEditorPart getActiveEditor() {
		return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); 
	}
	
	/**
	 * action executed when the add button is pressed.
	 */
	public void synchronizeButtonPressed() {
		SynchronizeWithGenericElementsDialog dialog = new SynchronizeWithGenericElementsDialog(
							Display.getCurrent().getActiveShell(), 
							LookForElement.topPackage(element.getUml2Element()),
							element.getRequiredSynchronizationActions()) ;
		dialog.open() ;
		if (dialog.getReturnCode() == Window.OK) {
			CommandStack stack = CommandStackUtils.getCommandStack() ;
			SynchronizationWithBoundElementsCommand synchronizationCommand = new SynchronizationWithBoundElementsCommand(element.getRequiredSynchronizationActions()) ;
			stack.execute(synchronizationCommand) ;
		}
	}
		
	/**
	 * Listener for the Add Button
	 * Specific behavior is implemented in {@link SynchronizeWithGenericElementsComposite#synchronizeButtonPressed()}.
	 * 
	 * @author Remi SCHNEKENBURGER
	 */
	private class SynchronizeButtonlistener implements MouseListener {
		
		/**
		 * 
		 * 
		 * @param e 
		 */
		public void mouseDoubleClick(MouseEvent e) {
			// do nothing
		}
		
		/**
		 * 
		 * 
		 * @param e 
		 */
		public void mouseDown(MouseEvent e) {
			// do nothing
		}
		
		/**
		 * 
		 * 
		 * @param e 
		 */
		public void mouseUp(MouseEvent e) {
			synchronizeButtonPressed();
			refresh();
		}
	}
	
	/**
	 * removes listeners from buttons.
	 */
	public void dispose() {
		if(synchronizeButton!=null && !synchronizeButton.isDisposed())
			synchronizeButton.removeMouseListener(synchronizeButtonlistener);
	}
}
